home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / emerald / emrldsys.lha / Kernel / Em / lmCode.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-08-17  |  16.7 KB  |  460 lines

  1.  
  2. /**************************************************************************/
  3. /*  C O P Y R I G H T   N O T I C E :                                     */
  4. /* Copyright 1986 Eric Jul.  May not be used for any               */
  5. /* purpose without written permission from the author.              */
  6. /**************************************************************************/
  7.  
  8. /****************************************************************/
  9. /*          Large Message Administration                        */
  10. /****************************************************************/
  11.  
  12. #include <sys/types.h>
  13. #include <errno.h>
  14. #include <sys/file.h>
  15. #include <sys/ioctl.h>
  16.  
  17. #include "Kernel/h/assert.h"
  18. #include "Kernel/h/macros.h"
  19. #include "Kernel/h/system.h"
  20. #undef integer
  21.  
  22. #include "Kernel/h/mmTypes.h"
  23. #include "Kernel/h/mmCodes.h"
  24. #include "Kernel/h/mmMsgDefs.h"
  25. #include "Kernel/h/mmMsgTypes.h"
  26. #include "Kernel/h/mmEthrTypes.h"
  27. #include "Kernel/h/unixCodes.h"
  28. #include "Kernel/h/mmBufTypes.h"
  29. #include "Kernel/h/mmFifoTypes.h"
  30. #include "Kernel/h/kmdTypes.h"
  31. #include "Kernel/h/kEvents.h"
  32. #include "Kernel/h/lmTypes.h"
  33. #include "Kernel/h/lmCodes.h"
  34. #include "Kernel/h/hotsTypes.h"
  35.  
  36. /*++BRDADDR++*/
  37. #include <net/if.h>
  38. /*--BRDADDR--*/
  39.  
  40. #define endcase break
  41.  
  42. extern int  DisplayEdenMsg(),
  43.         GetEdenMsg(),
  44.         PutEdenMsg();
  45.  
  46. /****************************************************************/
  47. /*                                                              */
  48. /*              L A R G E   M E S S A G E S                     */
  49. /*                                                              */
  50. /* The Large Message addition allows the transmission of        */
  51. /* messages of unbounded size.                                  */
  52. /* Messages are composed by passing references to the data to   */
  53. /* a macro which in turn copies the data into messages and      */
  54. /* sends it to another host.  At the destination, the packets   */
  55. /* making up the message are collected and when all packets     */
  56. /* have been reliably received, then a handler for the message  */
  57. /* is invoked.  It is passed a handle through which it may      */
  58. /* access the data by using a macro that will copy part or all  */
  59. /* of the data into a given buffer.                             */
  60. /* The packets are allocated and deallocated by this module.    */
  61. /* The packets are delivered reliably via MMSendMsg which uses  */
  62. /* the reliable sliding window protocol implemetned in the      */
  63. /* message module.                                              */
  64. /* Only one message may be composed at a time (this is an       */
  65. /* implementation restriction met by the Emerald Kernel).       */
  66. /*                                                              */
  67. /* The packets are transmitted as they are filled although the  */
  68. /* message is not delivered to the destination handler until    */
  69. /* all the packets have been successfully delivered.            */
  70. /*                                                              */
  71. /* Calling sequence:                                            */
  72. /*      LMStartMsg(&fHandle, MsgType, MsgSubtype, LNN )         */
  73. /*                                  returns a handle            */
  74. /*      LMPutData(&fHandle, dataPtr, length)  puts data into msg*/
  75. /*      ...                                                     */
  76. /*      LMSendMsg(&fHandle)          completes the msg send     */
  77. /*                                                              */
  78. /* Receiving sequence:                                          */
  79. /*      MMDefineMsgHandler(MsgType, MsgSubtype, Handler)        */
  80. /*      Handler(fHandle):                                       */
  81. /*      loop                                                    */
  82. /*          LMGetData(&fHandle, dataPtr, length)                */
  83. /*      exit when length = 0                                    */
  84. /*          <process data>                                      */
  85. /*      end loop                                                */
  86. /*      LMClose(&fHandle)                                       */
  87. /*                                                              */
  88. /*      The data may be reread any number of times by using     */
  89. /*      LMSeek(&fHandle, position, direction)                   */
  90. /*      which works much like lseek of UNIX fame.               */
  91. /*      LMCurrentPosition(&fHandle) returns current byte pos    */
  92. /*      from the start of the file.                             */
  93. /*                                                              */
  94. /****************************************************************/
  95.  
  96. /************************************************************/
  97. /*                                                          */
  98. /*                    LMStartMsg                            */
  99. /*                                                          */
  100. /*  LMStartMsg allocates a long message and returns         */
  101. /*  a handle.  The long message may only be accessed thru   */
  102. /*                                                          */
  103. /************************************************************/
  104.  
  105. KKStatus LMStartMsg(fHandle, fMsgType, fMsgSubtype, fLNN)
  106. LMHandle        *fHandle;
  107. MessageType      fMsgType;
  108. MessageSubtype   fMsgSubtype;
  109. NodeNum          fLNN;
  110. {
  111.     KKStatus                kstat;
  112.     LMMsgPtr                theMsg;
  113.  
  114.     KMDTrace("LM", 4, "New Long Msg to %d (0x%08x,0x%08x)\n",
  115.     fLNN, fMsgType, fMsgSubtype);
  116.     kstat = MMAllocateMsg(MAXMESSAGESIZE, (MessagePtr *)&theMsg);
  117.     if (!mSUCCESS(kstat)) return kstat;
  118.     MMBuildMsg((MessagePtr)theMsg, KMSG_LongMsg, LMM_LongMsg, fLNN,
  119.       MAXMESSAGESIZE);
  120.     theMsg->lmMsgHdr.ptr = (DataBytePtr) &theMsg->data[0];
  121.     theMsg->lmMsgHdr.limit = ((DataBytePtr) theMsg->lmMsgHdr.ptr) +
  122.                         MAXLMMESSAGESIZE;
  123.     theMsg->lmMsgHdr.realMsgType = fMsgType;
  124.     theMsg->lmMsgHdr.realMsgSubtype = fMsgSubtype;
  125.     theMsg->lmMsgHdr.flags.id = 1;
  126.     theMsg->lmMsgHdr.flags.last = 0;
  127.     *fHandle = theMsg;
  128.     return LMS_Success;
  129. }
  130.  
  131. /************************************************************/
  132. /*                                                          */
  133. /*                    LMPutLongData                         */
  134. /*                                                          */
  135. /*  Places the data into a long msg specified by a handle.  */
  136. /*  The data may be any size.                               */
  137. /*                                                          */
  138. /************************************************************/
  139.  
  140. KKStatus LMPutLongData(fHandle, fDataPtr, fDataLength)
  141. LMHandle                   *fHandle;
  142. DataBytePtr                 fDataPtr;
  143. unsigned int                fDataLength;
  144. {
  145.     KKStatus                kstat;
  146.     LMMsgPtr                theMsg;
  147.     register LMMsgHeaderPtr hdr, nextHdr;
  148.     register int            length = fDataLength;
  149.     register int            avail;
  150.     DataBytePtr             theData = fDataPtr;
  151.     LMMsgPtr                theNextMsg;
  152.  
  153.     KMDTrace("LM", 4, "LMPutLongData, handle=0x%08x, id %d, length %d\n",
  154.     *fHandle, ((LMMsgPtr) *fHandle)->lmMsgHdr.flags.id, fDataLength);
  155.  
  156.     theMsg = *fHandle;
  157.     hdr = &theMsg->lmMsgHdr;
  158.     while (length > 0) {
  159.     avail = (hdr->limit - hdr->ptr);
  160.     KMDTrace("LM", 5, "avail = %d\n", avail);
  161.     if (avail < length) {
  162.         /* Did not fit */
  163.         /* fill out packet, allocate a new packet, and send the old */
  164.         bcopy((char *)theData, (char *)hdr->ptr, avail);
  165.         hdr->ptr += avail;
  166.         length -= avail;
  167.         theData += avail;
  168.         kstat = MMAllocateMsg(MAXMESSAGESIZE, (MessagePtr *)&theNextMsg);
  169.         if (!mSUCCESS(kstat)) {
  170.         ErrMsg("LMPutLongMsg: 0x%08x, (no memory)\n", kstat);
  171.         assert(mSUCCESS(kstat));
  172.         };
  173.         MMBuildMsg((MessagePtr)theNextMsg, KMSG_LongMsg, LMM_LongMsg,
  174.         theMsg->mmMsgHdr.MsgDest, MAXMESSAGESIZE);
  175.         nextHdr = &theNextMsg->lmMsgHdr;
  176.         nextHdr->ptr  = (DataBytePtr) &theNextMsg->data[0];
  177.         nextHdr->limit = ((DataBytePtr) theNextMsg->lmMsgHdr.ptr) +
  178.                         MAXLMMESSAGESIZE;
  179.         nextHdr->flags.id = hdr->flags.id+1;
  180.         nextHdr->flags.last = 0;
  181.         KMDTrace("LM", 4, "Sending LongMsg packet #%d\n", hdr->flags.id);
  182.         if (!mSUCCESS(kstat = MMSendMsg((MessagePtr) theMsg))) {
  183.         ErrMsg("Cannot send LMMsg 0x%08x\n", kstat);        
  184.         };
  185.         MMDeallocateMsg((MessagePtr) theMsg);
  186.         theMsg = theNextMsg;
  187.         *fHandle = theMsg;
  188.         hdr = nextHdr;
  189.     } else {
  190.         /* Fit */
  191.         KMDTrace("LM", 4, " packing %d bytes into packet\n", length);
  192.         bcopy((char *)theData, (char *)hdr->ptr, length);
  193.         hdr->ptr += length;
  194.         length = 0;
  195.     }
  196.     }
  197. }
  198.  
  199. /**********************************************************************/
  200. /*      LMMsgHandler                                                  */
  201. /**********************************************************************/
  202.  
  203. HResult LMMsgHandler(fMsg)
  204. LMMsgPtr          fMsg;
  205. /* Put the packet into the queue and invoke the real handler if the packet
  206.    was the last packet. */
  207. {
  208.     KKStatus                kstat;
  209.     register LMMsgPtr       theMsg = fMsg;
  210.     register LMMsgHeaderPtr hdr = &theMsg->lmMsgHdr;
  211.     register int            length;
  212.     LMHandle                theFirstMsg;
  213.     HOTSRecord             *hotp;
  214.  
  215.     KMDTrace("LM", 4, "Long Msg packet (LNN %d, #%d) arrived\n",
  216.     theMsg->mmMsgHdr.MsgSrc, hdr->flags.id);
  217.     length = theMsg->mmMsgHdr.MsgSize - sizeof(LMMsgHeader);
  218.     KMDTrace("LM", 5, "  data length (excluding headers) = %d\n", length);
  219.     hdr->ptr = &theMsg->data[0];
  220.     hdr->limit = hdr->ptr + length;
  221.     
  222.     kstat = HOTSSearchPtr(theMsg->mmMsgHdr.MsgSrc, &hotp);
  223.     if (!mSUCCESS(kstat)) {
  224.     /* Hmm, it SHOULD be there. */
  225.     ErrMsg(
  226.             "Serious: Could not find LNN %d in HOTS table in LMMsgHandler\n",
  227.         theMsg->mmMsgHdr.MsgSrc);
  228.     return;
  229.     }
  230.     
  231.     QueueIns(hotp->incomingLMQueue, theMsg, lmMsgHdr.next);
  232.     if (hdr->flags.last) {
  233.         KMDTrace("LM", 3, "LMMsg from #%d, total size %d bytes (+%d hdr)\n",
  234.             theMsg->mmMsgHdr.MsgSrc,
  235.         length + (hdr->flags.id - 1) * MAXLMMESSAGESIZE,
  236.             sizeof(MessageHeader) + sizeof(LMMsgHeader));
  237.     theFirstMsg = hotp->incomingLMQueue->lmMsgHdr.next;
  238.     theFirstMsg->mmMsgHdr.MsgType = theFirstMsg->lmMsgHdr.realMsgType;
  239.     theFirstMsg->mmMsgHdr.MsgSubtype =
  240.                     theFirstMsg->lmMsgHdr.realMsgSubtype;
  241.     KMDTrace("LM", 5, "incomingQ 0x%08x, firstMsg 0x%08x\n",
  242.         hotp->incomingLMQueue, theFirstMsg);
  243.     QueueInit(hotp->incomingLMQueue);
  244.     if (!mSUCCESS(kstat = MMDispatchMsg((MessagePtr) theFirstMsg))) {
  245.         ErrMsg("Could not dispatch LM, status 0x%08x\n", kstat);
  246.         LMClose(&theFirstMsg);
  247.         return;
  248.     };
  249.     }
  250. }
  251.  
  252.  
  253. /**********************************************************************/
  254. /*      LMSendMsg                                                     */
  255. /**********************************************************************/
  256.  
  257. KKStatus LMSendMsg(fHandle)
  258. LMHandle        *fHandle;
  259. /* Complete the last packet and send it. */
  260. {    
  261.     KKStatus                kstat;
  262.     LMMsgPtr                theMsg = *fHandle;
  263.     register LMMsgHeaderPtr hdr = &theMsg->lmMsgHdr;
  264.  
  265.     *fHandle =(LMHandle) NULL;
  266.     KMDTrace("LM", 3,
  267.         "Sending last LM packet (#%d), total msg size %d (+%d hdr)\n",
  268.     hdr->flags.id, ((hdr->ptr - (&(theMsg->data[0]))) +
  269.     ((hdr->flags.id - 1) * MAXLMMESSAGESIZE)),
  270.         sizeof(MessageHeader) + sizeof(LMMsgHeader));
  271.     hdr->flags.last = 1;
  272.     /* Fix the size */
  273.     theMsg->mmMsgHdr.MsgSize = (hdr->ptr - &theMsg->data[0]) +
  274.     sizeof(LMMsgHeader);
  275.     KMDTrace("LM", 4, "  last packet size %d\n", theMsg->mmMsgHdr.MsgSize);
  276.     kstat = MMSendMsg((MessagePtr) theMsg);
  277.     if (!mSUCCESS(kstat)) {
  278.     ErrMsg("LMSendMsg: bad kstat 0x%02x\n", kstat);
  279.     }
  280.     MMDeallocateMsg((MessagePtr) theMsg);
  281.     return kstat;
  282. }    
  283.  
  284.  
  285. /************************************************************/
  286.  
  287. KKStatus LMBroadcastMsg(fHandle)
  288. LMHandle        *fHandle;
  289. /* Send out a LM broadcast. Note: must be small enough !!! */
  290. {    
  291.     KKStatus                kstat;
  292.     LMMsgPtr                theMsg = *fHandle;
  293.     register LMMsgHeaderPtr hdr = &theMsg->lmMsgHdr;
  294.     int                     totalSize;
  295.  
  296.     *fHandle =(LMHandle) NULL;
  297.     totalSize =  ((hdr->ptr - (&(theMsg->data[0]))) +
  298.     ((hdr->flags.id - 1) * MAXLMMESSAGESIZE));
  299.     KMDTrace("LM", 3, "Sending broadcast LMMsg packet, total size %d\n", totalSize);
  300.     /* Check for max broadcast size */
  301.     assert(totalSize < 1400);
  302.     hdr->flags.last = 1;
  303.     /* Fix the size */
  304.     theMsg->mmMsgHdr.MsgSize = (hdr->ptr - &theMsg->data[0]) +
  305.     sizeof(LMMsgHeader);
  306.     kstat = MMBroadcastMsg((MessagePtr) theMsg);
  307.     if (!mSUCCESS(kstat)) {
  308.     ErrMsg("LMBroadcastMsg: bad kstat 0x%02x\n", kstat);
  309.     }
  310.     MMDeallocateMsg((MessagePtr) theMsg);
  311.     return kstat;
  312. }    
  313.  
  314.  
  315. /************************************************************/
  316.  
  317. void LMGetLongData(fHandle, fDataPtr, fDataLength)
  318. LMHandle               *fHandle;
  319. DataBytePtr             fDataPtr;
  320. unsigned int           *fDataLength;
  321. /* Get a chunk of data out of one (or more) LM packets. */
  322. {
  323.     LMMsgPtr                theMsg;
  324.     register LMMsgHeaderPtr hdr, nextHdr;
  325.     int                     sum = 0;
  326.     register int            length = *fDataLength;
  327.     register unsigned int   avail;
  328.     DataBytePtr             theData = fDataPtr;
  329.     LMMsgPtr                theNextMsg;
  330.  
  331.     KMDTrace("LM", 4, "LMGetLongData, handle=0x%08x, id %d, length %d\n",
  332.     *fHandle, (*fHandle)->lmMsgHdr.flags.id, *fDataLength);
  333.  
  334.     theMsg = *fHandle;
  335.     assert(theMsg != NULL);
  336.     hdr = &theMsg->lmMsgHdr;
  337.     while (length > 0) {
  338.     avail = (hdr->limit - hdr->ptr);
  339.     KMDTrace("LM", 4, "avail = %d\n", avail);
  340.     if (avail < length) {
  341.         /* Not enough data in this buffer */
  342.         bcopy((char *)hdr->ptr, (char *)theData, (int)avail);
  343.         hdr->ptr += avail;
  344.         length -= avail;
  345.         theData += avail;
  346.         sum += avail;
  347.  
  348.         if(hdr->flags.last){
  349.         *fDataLength = sum;
  350.         return;
  351.         }
  352.  
  353.         theNextMsg = hdr->next;
  354.         nextHdr = &theNextMsg->lmMsgHdr;
  355.         nextHdr->ptr  = (DataBytePtr) &theNextMsg->data[0];
  356.         nextHdr->limit = ((DataBytePtr) nextHdr) +
  357.                     theNextMsg->mmMsgHdr.MsgSize;
  358.         KMDTrace("LM", 4, "Opening LMpacket #%d, size %d\n", hdr->flags.id,
  359.         nextHdr->limit - nextHdr->ptr);
  360.         theMsg = theNextMsg;
  361.         *fHandle = theMsg;
  362.         hdr = nextHdr;
  363.     } else {
  364.         /* Fit */
  365.         bcopy((char *)hdr->ptr, (char *)theData, length);
  366.         hdr->ptr += length;
  367.         sum += length;
  368.         length = 0;
  369.     }
  370.     }
  371.     *fDataLength = sum;
  372. }
  373.  
  374. long LMCurrentPosition(fHandle)
  375. LMHandle        *fHandle;
  376. {
  377.     register long current;
  378.     register LMHandle theMsg = *fHandle;
  379.     
  380.     current = (theMsg->lmMsgHdr.ptr - &theMsg->data[0] ) +
  381.         (theMsg->lmMsgHdr.flags.id - 1) * MAXLMMESSAGESIZE;
  382.     KMDTrace("LM", 3, "LMCurrentPosition %d\n", current);
  383.     return(current);
  384. }
  385.  
  386. KKStatus LMSeek(fHandle, fPosition, fDirection)
  387. LMHandle        *fHandle;
  388. long            fPosition, fDirection;
  389. /* Seek as for lseek, fDirection:  0: from start, 1: relative, 2: from end */
  390. {
  391.     long    current, desired, wantId, desiredLocalPosition;
  392.     LMHandle theMsg = *fHandle;
  393.  
  394.     current = theMsg->lmMsgHdr.ptr -
  395.         (DataBytePtr) theMsg->data[0] +
  396.         (theMsg->lmMsgHdr.flags.id - 1) * MAXLMMESSAGESIZE;
  397.     KMDTrace("LM", 3, "LMSeek current pos %d, offset %d\n", current,
  398.     fPosition);
  399.  
  400.     switch ((int)fDirection) {
  401.     case 0:     /* Offset from start of msg */
  402.     desired = fPosition;
  403.     break;
  404.     
  405.     case 1:     /* Offset from current Position */
  406.     desired = current + fPosition;
  407.     break;
  408.  
  409.     case 2:     /* Offset form end of file */
  410.     assert(FALSE);
  411.     break;
  412.     
  413.     default:
  414.     assert(FALSE);
  415.     }
  416.     wantId = (desired / MAXLMMESSAGESIZE) +1;
  417.     desiredLocalPosition = desired % MAXLMMESSAGESIZE;
  418.     KMDTrace("LM", 4, "Seeking msgId %d, position %d\n", wantId,
  419.     desiredLocalPosition);    
  420.     for(;theMsg->lmMsgHdr.flags.id != wantId; theMsg = theMsg->lmMsgHdr.next);
  421.     theMsg->lmMsgHdr.ptr = &theMsg->data[desired % MAXLMMESSAGESIZE];
  422. }
  423.  
  424. /************************************************************************/
  425. void LMClose(fHandle)
  426. LMHandle        *fHandle;
  427. {
  428.     LMHandle    theNextMsg, firstDealloced, theMsg = *fHandle;
  429.     int         id;
  430.  
  431.     KMDTrace("LM", 4, "Finished with Long Msg\n");
  432.     firstDealloced = theMsg;    
  433.     do {
  434.     theNextMsg = theMsg->lmMsgHdr.next;
  435.     id =         theMsg->lmMsgHdr.flags.id;
  436.     KMDTrace("LM", 5, "Deallocate packet #%d\n", id);
  437.     MMDeallocateMsg((MessagePtr) theMsg);
  438.     theMsg = theNextMsg;
  439.     } while (theNextMsg != firstDealloced);
  440.     *fHandle = NULL;
  441. }
  442.  
  443. /************************************************************/
  444.  
  445. void LMInit()
  446. {
  447.     KMDSetTrace(LM);
  448.     
  449.     KMDTrace("LM", 5,
  450.         "LMInit Byte sizes MMHdr:%d, LMHdr%d, max useful in packet %d\n",
  451.     sizeof(MessageHeader), sizeof(LMMsgHeader), MAXLMMESSAGESIZE);
  452.     MMDefineMsgHandler(KMSG_LongMsg, LMM_LongMsg, (HandlerPtr)LMMsgHandler,
  453.       (HandlerPtr *)NULL);
  454. }
  455.  
  456.  
  457. /************************************************************/
  458. /*      E N D   O F   L A R G E    M E S S A G E            */
  459. /************************************************************/
  460.